package org.qianji.goosql.cond;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.qianji.goosql.exception.ConditionException;
import org.qianji.goosql.field.Field;
import org.qianji.goosql.operator.Comparator;

/**
 * IN确定范围查询条件。
 * 
 * @author gmz
 * 
 */
public class InValues extends In {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1244789802000640700L;

	private List<Object> values = new ArrayList<Object>();

	/**
	 * 构造IN确定范围查询条件。
	 * 
	 * @param field
	 *            {@link Field} 查询字段
	 * @param values
	 *            {@link Object} IN的范围
	 */
	public InValues(Field field, Object... values) {
		super();
		if (field == null || values == null || values.length == 0) {
			throw new NullPointerException("args can't be null");
		}
		this.field = field;
		for (Object val : values) {
			if (val != null && !this.values.contains(val)) {
				this.values.add(val);
			}
		}
	}

	/**
	 * 获取IN的范围
	 * 
	 * @return {@link Object} IN的范围
	 */
	public List<Object> getValues() {
		return values;
	}

	/**
	 * 获取IN范围大小
	 * 
	 * @return {@link java.lang.Integer int} IN范围大小
	 */
	public int size() {
		return (values != null ? values.size() : 0);
	}

	private void assertEmpty() {
		if (size() == 0) {
			throw new ConditionException("In Condition is empty");
		}
	}

	@Override
	public String toSql() {
		assertEmpty();
		StringBuffer cond = new StringBuffer(field.toSql()).append(" ");
		int size = size();
		if (size == 1) {
			cond.append(Comparator.EQ).append(" ?");
		} else {
			cond.append(Comparator.IN).append(" (?");
			for (int i = 1; i < size; i++) {
				cond.append(",?");
			}
			cond.append(")");
		}
		return cond.toString();
	}

	@Override
	public List<Object> getPlacedParameters() {
		assertEmpty();
		List<Object> ppl = new ArrayList<Object>();
		ppl.addAll(field.getPlacedParameters());
		ppl.addAll(getValues());
		return ppl;
	}

	@Override
	public Map<String, Object> getNamedParameters() {
		assertEmpty();
		return field.getNamedParameters();
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null || !(obj instanceof InValues)) {
			return false;
		}
		InValues other = (InValues) obj;
		if (field.equals(other.getField()) && size() == other.size()) {
			for (Object val : other.getValues()) {
				if (!values.contains(val)) {
					return false;
				}
			}
			return true;
		}
		return false;
	}

	@Override
	public int hashCode() {
		int hc = 37 * 17 + field.hashCode();
		for (Object val : values) {
			hc = 37 * hc + (val != null ? val.hashCode() : 0);
		}
		return hc;
	}

	@Override
	public String toString() {
		return toSql();
	}

}
